#include "disk.h"
#include "daemon.h"
#include "action.h"
#include "avdfile.h"
#include "fileerror.h"
#include "foldererror.h"

#include <QFile>
#include <QDir>

#include <iostream>
using std::cerr;
using std::cout;
using std::endl;

namespace Avd {

Disk::Disk(const QString &absolutePath, Daemon* daemon) : Folder("",""), absolutePath(absolutePath), daemon(daemon) {
	QDir dir("/");
	dir.mkdir(absolutePath);
}

Disk::~Disk() { }

QList<Action *> Disk::check() {
	AvdFile avdFile(absolutePath, "");
	return avdFile.check();
}

void Disk::save(File& file, const bool saveData) throw(FileSystemError) {
	if(saveData) {
		QString realPath;
		if(file.isTemp())
			realPath = cleanPath(absolutePath + "/" + file.getTempFullPath());
		else
			realPath = cleanPath(absolutePath + "/" + file.getFullPath());
		/* Save via QFile	 */
		QFile qfile(realPath);
		if(!qfile.open(QIODevice::ReadWrite))
			throw FileError("void Disk::save(File& file, const bool saveData): could not open the file to write.", file);
		if(qfile.write(file.getData(), file.getSize()) == -1)
			throw FileError("void Disk::update(File& file, const bool saveData): could not write.", file);
	}
	if(!file.isTemp()) {
		// If it is not a temporary file, just save it on .avd/files.
		AvdFile tbFile(absolutePath, file.getPath());
		tbFile.add(file);
	}
	else if(merge(file)) {
		AvdFile tbFile(absolutePath, file.getPath());
		tbFile.add(file);
	}
}

bool Disk::merge(File& file) {
	// Let's see if we can merge now.
	QDir tempDir(absolutePath + file.getPath());
	QStringList filesEntries = tempDir.entryList(QDir::Files);
	QStringList nameList = filesEntries.filter(file.getName());
	if(!nameList.isEmpty()) {
		QStringList splitList = nameList.at(0).split(".");
		if(splitList.size() < 3)
			return false;
		unsigned int version = splitList.takeLast().toInt();
		unsigned int totalParts = splitList.takeLast().toInt();
		if(nameList.size() == totalParts) {
			cout << "Devia juntar" << endl;
			QString realPath = cleanPath(absolutePath + "/" + file.getFullPath());
			QFile qfile(realPath);
			if(!qfile.open(QIODevice::ReadWrite))
				throw FileError("void Disk::save(File& file, const bool saveData): could not open the file to write.", file);
			// FIXME
//			if(qfile.write(file.getData(), file.getSize()) == -1)
//				throw FileError("void Disk::update(File& file, const bool saveData): could not write.", file);
			return true;
		}
	}
}

void Disk::remove(const File& file) throw(FileSystemError) {
	QString realPath = cleanPath(absolutePath + "/" + file.getFullPath());
	QFile qfile(realPath);
	qfile.remove();
	AvdFile tbFile(absolutePath, file.getPath());
	tbFile.remove(file);
}

void Disk::remove(const Folder& folder) throw(FileSystemError) {
	QDir parentDir(absolutePath + "/" + folder.getPath());
	AvdFile tbFile(absolutePath, folder.getPath());
	tbFile.remove(folder);
	parentDir.rmdir(folder.getName());
}

void Disk::move(const QString& oldPath, const QString& newPath) throw(FileSystemError) {
	QFileInfo oldEntry(oldPath);
	QString nonConstOldPath(oldPath);
	QString nonConstNewPath(newPath);
	if(oldEntry.isFile())
		move(File(nonConstOldPath, 0, 0), File(nonConstNewPath, 0, 0));
	else
		move(Folder(oldPath,0), Folder(newPath, 0));
}

void Disk::move(const Folder& oldFolder, const Folder& newFolder) throw(FileSystemError) {
	QDir oldDir(absolutePath + "/" + oldFolder.getFullPath());
	if(!oldDir.rename(oldDir.absolutePath(),absolutePath + "/" + newFolder.getFullPath()))
		throw FolderError("void Disk::move(const Folder& oldFolder, const Folder& newFolder): could not rename.", oldFolder);
}

void Disk::move(const File& oldFile, const File& newFile) throw(FileSystemError) {	//TODO FIXME
	QString oldRealPath = cleanPath(absolutePath + "/" + oldFile.getFullPath());
	QString newRealPath = cleanPath(absolutePath + "/" + newFile.getFullPath());
	QFile qOldFile(oldRealPath);
	qOldFile.open(QIODevice::ReadWrite);
	qOldFile.close();
	if(!qOldFile.rename(newRealPath))
		throw FileError("void Disk::move(const File& oldFile, const File& newFile): could not rename.", oldFile);

}

void Disk::update(File& file, const bool saveData) throw(FileSystemError) {
	QString realPath = cleanPath(absolutePath + "/" + file.getFullPath());
	QFile qfile(realPath);
	if(qfile.exists() && saveData) {
		if(!qfile.remove()) {
			throw FileError("void Disk::update(File& file, const bool saveData): could not remove old file.", file);
		}
	}
	save(file, saveData);
}

void Disk::create(const Folder& folder) throw(FileSystemError) {
	QDir parentDir(absolutePath + "/" + folder.getPath());
	if(QDir(absolutePath + "/" + folder.getFullPath()).exists()) {
		AvdFile tbFile(absolutePath, folder.getPath());
		tbFile.add(folder);
	}
	else {
		if(!parentDir.mkdir(folder.getName()))
			throw FolderError("void Disk::create(const Folder& folder): could not create folder.", folder);
		AvdFile tbFile(absolutePath, folder.getPath());
		tbFile.add(folder);
	}
}



}


